package labox.innovation.gameserver;

import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import labox.innovation.config.Config;

import labox.innovation.gameserver.util.StringUtil;

/**
 * 所有的线程池管理类
 */
public final class ThreadPoolManager {

	protected static final Logger _log = LoggerFactory.getLogger(ThreadPoolManager.class.getName());

	// temp
	private ScheduledThreadPoolExecutor _ioThreadPool;

	public static ThreadPoolManager getInstance() {
		return SingletonHolder._instance;
	}

	private ThreadPoolManager() {
		_ioThreadPool = new ScheduledThreadPoolExecutor(Config.GENERAL_THREAD_CORE_SIZE, new PriorityThreadFactory("CoreThreadPool", Thread.NORM_PRIORITY), new RejectedHandler());
	}

	public ScheduledFuture<?> scheduleWithFixedDelay(Runnable r, long initial, long delay) {
		try {
			return _ioThreadPool.scheduleWithFixedDelay(r, initial, delay, TimeUnit.MILLISECONDS);
		} catch (RejectedExecutionException e) {
			return null; /* shutdown, ignore */
		}
	}

	public ScheduledFuture<?> scheduleAtFixedRate(Runnable r, long initial, long delay) {
		try {
			return _ioThreadPool.scheduleAtFixedRate(r, initial, delay, TimeUnit.MILLISECONDS);
		} catch (RejectedExecutionException e) {
			return null; /* shutdown, ignore */
		}
	}

	public ScheduledFuture<?> schedule(Runnable r, long initial) {
		try {
			return _ioThreadPool.schedule(r, initial, TimeUnit.MILLISECONDS);
		} catch (RejectedExecutionException e) {
			return null; /* shutdown, ignore */
		}
	}

	public void execute(Runnable pkt) {
		_ioThreadPool.execute(pkt);
	}

	public void remove(Runnable task) {
		_ioThreadPool.remove(task);
	}

	public String[] getStats() {
		return new String[] { "STP:", "|- getCorePoolSize: " + _ioThreadPool.getCorePoolSize(), " |- Not Done" };
	}

	/**
	 * 处理
	 * 
	 * @author Administrator
	 * 
	 */
	private static class RejectedHandler implements RejectedExecutionHandler {

		@Override
		public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
			if (Engine.getInstance().isClose()) {
				return;
			} else {
				executor.execute(r);
			}
		}

	}

	/**
	 * 线程工厂类，主要用来设定名称和分组，便于统计和查看
	 * 
	 * @author Administrator
	 * 
	 */
	private static class PriorityThreadFactory implements ThreadFactory {
		private int _prio;

		private String _name;

		private AtomicInteger _threadNumber = new AtomicInteger(1);

		private ThreadGroup _group;

		public PriorityThreadFactory(String name, int prio) {
			_prio = prio;
			_name = name;
			_group = new ThreadGroup(_name);
		}

		/* (non-Javadoc)
		 * @see java.util.concurrent.ThreadFactory#newThread(java.lang.Runnable)
		 */
		public Thread newThread(Runnable r) {
			Thread t = new Thread(_group, r);
			t.setName(_name + "-" + _threadNumber.getAndIncrement());
			t.setPriority(_prio);
			return t;
		}

		public ThreadGroup getGroup() {
			return _group;
		}
	}

	/**
	 *
	 */
	public void shutdown() {
		try {
			_ioThreadPool.awaitTermination(1, TimeUnit.SECONDS);
			_ioThreadPool.shutdown();
			_log.info("All ThreadPools are now stoped", Config.SERVER_ID, "线程池关闭");
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public boolean isShutdown() {
		return _ioThreadPool == null || _ioThreadPool.isShutdown();
	}

	/**
	 *
	 */
	public void purge() {
		_ioThreadPool.purge();
	}

	public String getIOPacketStats() {
		final StringBuilder sb = new StringBuilder(1000);
		ThreadFactory tf = _ioThreadPool.getThreadFactory();

		if (tf instanceof PriorityThreadFactory) {
			PriorityThreadFactory ptf = (PriorityThreadFactory) tf;
			int count = ptf.getGroup().activeCount();
			Thread[] threads = new Thread[count + 2];
			ptf.getGroup().enumerate(threads);
			StringUtil.append(sb, "I/O Packet Thread Pool:\r\n" + "Tasks in the queue: ", String.valueOf(_ioThreadPool.getQueue().size()), "\r\n" + "Showing threads stack trace:\r\n" + "There should be ", String.valueOf(count), " Threads\r\n");

			for (Thread t : threads) {
				if (t == null)
					continue;

				StringUtil.append(sb, t.getName(), "\r\n");

				for (StackTraceElement ste : t.getStackTrace()) {
					StringUtil.append(sb, ste.toString(), "\r\n");
				}
			}
		}

		sb.append("Packet Tp stack traces printed.\r\n");

		return sb.toString();
	}

	@SuppressWarnings("synthetic-access")
	private static class SingletonHolder {
		protected static final ThreadPoolManager _instance = new ThreadPoolManager();
	}
}